package com.he.hsdyc.service.impl;


import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.he.hsdyc.common.utils.DateUtil;
import com.he.hsdyc.mapper.*;
import com.he.hsdyc.model.vo.CourseOrderVo;
import com.he.hsdyc.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import static com.he.hsdyc.common.utils.DateUtil.getNowTime;


@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private RechargeMapper rechargeMapper;
    @Autowired
    private WithdrawalRecordMapper withdrawalRecordMapper;

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderFlowRecordMapper orderFlowRecordMapper;
    @Autowired
    private OrderClassPackageMapper orderClassPackageMapper;
    @Autowired
    private OrderClassPackageFlowRecordMapper orderClassPackageFlowRecordMapper;
    @Autowired
    private OrderGoodsMapper orderGoodsMapper;
    @Autowired
    private OrderGoodsFlowRecordMapper orderGoodsFlowRecordMapper;


    @Override
    public Map<String, Object> listback(CourseOrderVo vo) {

        //全部则传全部状态
        ArrayList<Integer> orderStatus = changeStatus(vo.getStatus());
        vo.setOrderStatus(orderStatus);

        com.github.pagehelper.Page<Map<String, Object>> page = PageHelper.startPage(vo.getPageNo(), vo.getPageSize());
        com.github.pagehelper.Page<Map<String, Object>> datas = (com.github.pagehelper.Page<Map<String, Object>>) orderMapper.listback(vo);
        datas.getResult().stream()
                .forEach(map -> {
                    if(map.get("status") != null && (Integer.parseInt(map.get("status").toString()) == 1 || Integer.parseInt(map.get("status").toString()) == 3)) {
                        BigDecimal money = BigDecimal.ZERO;
                        if(vo.getDel() != null && vo.getDel()) {
                            money = orderMapper.countRefundsByOrderDelete(Long.parseLong(map.get("id").toString()));
                        }
                        else money = orderMapper.countRefundsByOrder(Long.parseLong(map.get("id").toString()));
                        if(money != null)
                            map.put("discount",new BigDecimal(map.get("discount").toString()).subtract(money).setScale(2,BigDecimal.ROUND_DOWN));
                    }
                    if(map.get("status") != null && (Integer.parseInt(map.get("status").toString()) == 0 || Integer.parseInt(map.get("status").toString()) == 4  || Integer.parseInt(map.get("status").toString()) ==5))
                        map.put("discount",new BigDecimal(0).setScale(2,BigDecimal.ROUND_DOWN));
                });

        datas.setTotal(page.getTotal());
        PageInfo<Map<String, Object>> pageInfo = new PageInfo<>(datas);

        //6+新增订单统计
        Map<String,Object> map = new HashMap<>();
        map.put("pageInfo",pageInfo);

        if(vo.getDel() != null && !vo.getDel()) {
            //订单应收actualMoney，实收discountAll，尾款balanceAll
            //上面的lamda中求和，自定义局部变量在lamda内部无法被改变，只能单独计算
            BigDecimal actualMoneyAll = datas.getResult().stream()
                    .map(m -> m.get("actualMoney") == null ? BigDecimal.ZERO : new BigDecimal(m.get("actualMoney").toString()))
                    .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_DOWN);
            BigDecimal discountAll = datas.getResult().stream()
                    .map(m -> m.get("discount") == null ? BigDecimal.ZERO : new BigDecimal(m.get("discount").toString()))
                    .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_DOWN);
            BigDecimal balanceAll = datas.getResult().stream()
                    .map(m -> m.get("balanceType").toString().equals("0") ? new BigDecimal(m.get("balance").toString()) : BigDecimal.ZERO)
                    .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_DOWN);
            map.put("actualMoneyAll", actualMoneyAll);
            map.put("discountAll", discountAll);
            map.put("balanceAll", balanceAll);
        }
        return map;
    }


    /**
     * 功能描述: 抽取公用方法
     * @param: status 订单状态，逗号分割，其中交易关闭status = 0,4
     */
    public static ArrayList<Integer> changeStatus(String status) {
        String[] arr = new String[10];
        ArrayList<Integer> list = new ArrayList<>();
        if (status != null) {
            arr = status.split(",");
            for (String a : arr) {
                Integer s = Integer.parseInt(a);
                list.add(s);
            }
        }
        return list;
    }








    @Override
    public Map<String, Object> countOrder(CourseOrderVo vo) {
        Map<String, Object> map = new HashMap<>();
        //课程订单统计
        //不传时间统计所有
        Map<String, Object> countOrderAll = this.countOrderByTime(vo,1);
        //昨日业绩统计
        vo.setStartTime(DateUtil.getBeforeNDays(getNowTime(),1));
        vo.setEndTime(DateUtil.getBeforeNDays(getNowTime(),1));
        Map<String, Object> countOrderYest = this.countOrderByTime(vo,1);
        //组装返回数据
        map.put("orderAllAmount",countOrderAll.get("amountNew"));
        map.put("orderAllcount",countOrderAll.get("countNew"));
        map.put("orderAllFlows",countOrderAll.get("countFlows"));
        map.put("orderAllAmountYest",countOrderYest.get("amountNew"));
        map.put("orderAllcountYest",countOrderYest.get("countNew"));
        map.put("orderAllFlowsYest",countOrderAll.get("countFlows"));



        //组合包订单统计
        //不传时间统计所有
        vo.setStartTime(null);
        vo.setEndTime(null);
        Map<String, Object> countOrderClassPackageAll = this.countOrderByTime(vo,2);
        //昨日业绩统计
        vo.setStartTime(DateUtil.getBeforeNDays(getNowTime(),1));
        vo.setEndTime(DateUtil.getBeforeNDays(getNowTime(),1));
        Map<String, Object> countOrderClassPackageYest = this.countOrderByTime(vo,2);
        //组装返回数据
        map.put("orderClassPackageAllAmount",countOrderClassPackageAll.get("amountNew"));
        map.put("orderClassPackageAllcount",countOrderClassPackageAll.get("countNew"));
        map.put("orderClassPackageAllFlows",countOrderClassPackageAll.get("countFlows"));
        map.put("orderClassPackageAllAmountYest",countOrderClassPackageYest.get("amountNew"));
        map.put("orderClassPackageAllcountYest",countOrderClassPackageYest.get("countNew"));
        map.put("orderClassPackageAllFlowsYest",countOrderClassPackageAll.get("countFlows"));






        //商品订单统计
        //不传时间统计所有
        vo.setStartTime(null);
        vo.setEndTime(null);
        Map<String, Object> countOrderGoodsAll = this.countOrderByTime(vo,3);
        //昨日业绩统计
        vo.setStartTime(DateUtil.getBeforeNDays(getNowTime(),1));
        vo.setEndTime(DateUtil.getBeforeNDays(getNowTime(),1));
        Map<String, Object> countOrderGoodsYest = this.countOrderByTime(vo,3);
        //组装返回数据
        map.put("orderGoodsAllAmount",countOrderGoodsAll.get("amountNew"));
        map.put("orderGoodsAllcount",countOrderGoodsAll.get("countNew"));
        map.put("orderGoodsAllFlows",countOrderGoodsAll.get("countFlows"));
        map.put("orderGoodsAllAmountYest",countOrderGoodsYest.get("amountNew"));
        map.put("orderGoodsAllcountYest",countOrderGoodsYest.get("countNew"));
        map.put("orderGoodsAllFlowsYest",countOrderGoodsYest.get("countFlows"));







        //账户订单统计
        //不传时间统计所有
        vo.setStartTime(null);
        vo.setEndTime(null);
        Map<String, Object> countOrderAccountAll = this.countOrderByTime(vo,4);
        //昨日业绩统计
        vo.setStartTime(DateUtil.getBeforeNDays(getNowTime(),1));
        vo.setEndTime(DateUtil.getBeforeNDays(getNowTime(),1));
        Map<String, Object> countOrderAccountYest = this.countOrderByTime(vo,4);
        //组装返回数据
        map.put("orderAccountAllAmount",countOrderAccountAll.get("amountNew"));
        map.put("orderAccountAllcount",countOrderAccountAll.get("countNew"));
        map.put("orderAccountAllAmountYest",countOrderAccountYest.get("amountNew"));
        map.put("orderAccountAllAmountYest",countOrderAccountYest.get("countNew"));


        return map;
    }




    /**
     * 功能描述: 抽取公用方法
     * @param: 根据时间计算订单实收金额，实收条数
     */
    public Map<String,Object> countOrderByTime(CourseOrderVo vo,Integer type) {
        Map<String, Object> count = new HashMap<>();
        Map<String, Object> countRefunds =new HashMap<>();
        Integer countFlows = 0;
        if(type == 1) {//课程订单业绩
            count = orderMapper.countNew(vo);
            countRefunds = orderMapper.countRefunds(vo);
            countFlows = orderFlowRecordMapper.count(vo);
        }
        else if(type == 2) { //组合包订单业绩
            count = orderClassPackageMapper.countNew(vo);
            countRefunds = orderClassPackageMapper.countRefunds(vo);
            countFlows = orderClassPackageFlowRecordMapper.count(vo);
        }else if(type == 3){//商品订单业绩
            count = orderGoodsMapper.countNew(vo);
            countRefunds = orderGoodsMapper.countRefunds(vo);
            countFlows = orderGoodsFlowRecordMapper.count(vo);
        }else { //账户订单业绩 --------- 账户业绩=充值总实收-退费总实退
            //充值订单金额（实收）=个人充值实收+校方充值实收（不包括赠送金额）
            //消费订单金额（实收）=消费金额-退费转入
            //退费订单金额（实收）=退费金额实收（不包括扣除赠送金额）
            //充值金额、条数                                       充值订单金额（实收） = 个人充值实收 + 校方充值实收 （不包括赠送金额）
            Map<String, Object> countRecharge = rechargeMapper.count(vo);
            //退费金额、条数                                       退费订单金额（实收） = 退费金额实收（不包括扣除赠送金额）
            Map<String, Object> countWithdrawal = withdrawalRecordMapper.count(vo);
            count.put("amountNew",new BigDecimal(countRecharge.get("rechargeMoney").toString()).subtract(new BigDecimal(countWithdrawal.get("withdrawalMoney").toString())).setScale(2,BigDecimal.ROUND_DOWN));
            count.put("countNew",Integer.parseInt(countRecharge.get("rechargeCount").toString()) - Integer.parseInt(countWithdrawal.get("withdrawalCount").toString()));
            return count;
        }
        count.put("amountNew",new BigDecimal(count.get("amountNew").toString()).subtract(new BigDecimal(countRefunds.get("refundAmount").toString())).setScale(2,BigDecimal.ROUND_DOWN));
        count.put("countNew",Integer.parseInt(count.get("countNew").toString()) - Integer.parseInt(countRefunds.get("countRefund").toString()));
        count.put("countFlows",countFlows);
        return count;
    }






}


